package TAIC.LM ;
import java.nio.channels.*;
import java.util.*;
import java.io.* ;
import TAIC.Google.* ;
import TAIC.util.* ;

public class ImageRetrieve {
	//Vector < Sting > textPath [] = new Vector[ 2 ] ;
	public static final int RETRIVE_IMAGE = 35 ; 
	public static final int MAX_CLASS = 100;
	public static int IMAGE_PER_WORD = 8 ; 
	public static final int MAX_GET_IMAGE_THREAD = 50 ; 
	int totalKeys = 10 ;
	String configPath ; 
	String path [] = new String [ MAX_CLASS ] ;
	String testImage [] = new String [ MAX_CLASS ] ; 
	String classNames [] = new String [ MAX_CLASS ] ; 
//	String query [] = new String [ MAX_CLASS ] ; 
	String imageDataPath = "";
	int classes ;
	
	public ImageRetrieve ( String config ) {
		configPath = config ; 
	}

	static public void main ( String argu [] ) throws Exception {
		if ( argu.length != 1 ) {
			System.out.println ( "Please input arguments: the path of config file" ) ;
			return ; 
		}
		(new  ImageRetrieve  ( argu [ 0 ] )).run();
	}
	
	public void run () {
		int i , j , k ;
		GetImage [] getImage ;
		String [] imageUrl ; 
		ThreadPool tp = new ThreadPool ( 20 ) , tp1 = new ThreadPool ( MAX_GET_IMAGE_THREAD ) ; 
		/////////////   read from query2.txt to get information ///////////////////////////////
		preprocess () ;
		
		////////////////    to get key words from Bayes. Results are also stored in KeyWord.txt  //////////////////
		ArrayList < KeyWord > result = (new Bayes ( totalKeys )).getKey();
//		for ( i = 0 ;i < result.size() ; i ++ ) System.out.println ( result.get(i) ) ;
//		if ( true ) return ; 
		System.out.println ( "Bayesian Statical Calculation Complete" ) ;
		writeCache () ;
		
		
		//////////////////////////    calculate how many images to retrieve  \sum_P(v|w)P(w|c) ///////////////////
		int requiredImage [][] = new int [ result.size () / totalKeys ][ totalKeys ];   //  [ class ] [ word ]  
		for ( i =0 ; i < classes ; i ++ ) 
			for ( j = 0 ; j < totalKeys ; j ++ ) { 
				double total = 0.0 ; 
				for ( k = 0 ; k  <= j ; k ++ ) total += result.get( i * totalKeys + k ).prob; 
				requiredImage [ i ][ j ] = (int)Math.round ( Math.ceil( RETRIVE_IMAGE * result.get( i * totalKeys + j ).prob / total ));
				System.out.println ( i + " " +  j + " " + requiredImage [ i ][ j ]) ; 
			}
		
			
			
		//////////////////   Get Image Urls from google using the keyword generated above /////////////////////
		GImage [] gImage = new GImage [ result.size() ] ;		
		double prob ; 
		for ( i = 0 ; i < result.size() ; i ++ ) {
			KeyWord keyword = result.get ( i ) ; 
			//String s =  keyword.word ; 
			int currentClass = keyword.classNo  ;
			prob = keyword.prob ;
			String queryStr = keyword.word  ;
			if ( classNames [ currentClass ].indexOf ( queryStr ) != -1 ) queryStr = classNames [ currentClass ];
			else if ( queryStr.indexOf ( classNames [ currentClass ] ) == -1 ) queryStr = classNames [ currentClass ] + " " + queryStr;
			System.out.println ( queryStr ) ; 
			gImage [ i ] = new GImage ( (int)Math.round ( Math.ceil( requiredImage [ i / totalKeys][ i%totalKeys ]* 1.5 ) + 5 ),  queryStr ) ;
			tp.addThread ( gImage [ i ] ) ;
		}
		tp.join () ;
		System.out.println ( "Get Image Urls from Google Complete" ) ; 
		
		////////////////////     get specific image from web and strore them using the MD5 code as names  ///////////////////
		for ( i = 0 ; i < gImage.length ; i ++ ) {
			imageUrl = gImage [ i ].getResult () ;
			for ( j = 0 ; j < imageUrl.length ; j ++ ) {
				if ( imageUrl [ j ] == null || imageUrl[ j ].lastIndexOf ( '.' ) == -1 ) continue ;
				String localFile = caleName ( imageUrl [ j ] ) ; 
				if ( ! new File ( localFile ).exists() ) tp1.addThread ( new GetImage ( imageUrl[ j ] , imageDataPath + localFile )) ;
			}
		}
		tp1.join() ;
		System.out.println ( "All Images have been Retrieved from Internet" ) ;
		
		///////////////////////////////////      generate the final training and testing corpus //////////////////////////////////////
		PrintStream fout = null ;
		PrintStream fout1 = null ;
		
		try{
			fout = new PrintStream ( new File ( "ImageCorpus.txt" ) ) ;
			fout1 = new PrintStream ( new File ( "IP\\word2image.txt" ) ) ;
		}catch ( Exception e ) { e.printStackTrace () ; }

		for ( i = 0 ; i < gImage.length ; i ++ ) {
			imageUrl = gImage [ i ].getResult () ;
			int retrievedImage = 0 ; 
			for ( j = 0 ; j < imageUrl.length ; j ++ ) {
				if ( imageUrl [ j ] == null || imageUrl[ j ].lastIndexOf ( '.' ) == -1 ) continue ;				
				String localFile = caleName ( imageUrl [ j ] ) ; 
				if ( ( new File ( imageDataPath + localFile ) ).exists() ) {  
					if ( retrievedImage < requiredImage [ i / totalKeys][ i%totalKeys ] ) 
						fout.println ( result.get(i).classNo + " " + ( i % totalKeys ) + " " + imageDataPath + localFile ) ;
					retrievedImage ++ ; 
				}

			}
		}
		
		fout1.println ( classes + " " + totalKeys ) ; 
		for ( i = 0 ; i < gImage.length ; i ++ ) 
			fout1.println ( result.get(i).classNo + " " + (i%totalKeys)+ " " +  result.get(i).prob  ) ;
			//   word, classNo , wordNo , prob
		fout1.close() ;
		
		try {
			for ( i = 0 ; i < classes ; i ++ ) {
				Scanner scanner = new Scanner ( new File ( testImage  [ i ] + "index.txt" ) ) ; 
				//System.out.println ( testImage[ i ] + " " + i  ) ;
				while ( scanner.hasNextLine () ) {
					String s = testImage[ i ] + scanner.nextLine ().trim() ; 
					if ( (new File(s)).exists() ) fout.println ( (classes + i) + " 0 "  + s ) ; 
				}
			}
		}catch ( Exception e ) { e.printStackTrace () ; }
		fout.close() ; 
		
		System.out.println ( "All should be done had been done, Exit!" ) ;
		System.exit ( 0 ) ;
	}
	
    public void preprocess () {
		String s ;  
		int i , docs ;
		
		try {
		
		Scanner scanner = new Scanner ( new File ( configPath ) );
		scanner.next() ;
		totalKeys = scanner.nextInt () ; scanner.next () ;
		IMAGE_PER_WORD = scanner.nextInt() ; scanner.nextLine () ;
		imageDataPath = scanner.nextLine ().trim() ;
        classes = scanner.nextInt () ; scanner.nextLine () ; 
		for ( i = 0 ; i < classes ; i ++ ) classNames [ i ] = scanner.nextLine ().trim () ; 
        for ( i = 0 ; i < classes ; i ++ ) 
            path [ i ] = scanner.nextLine().trim() ;
		for ( i = 0 ; i  < classes ; i ++ ) 
			testImage [ i ] = scanner.nextLine().trim() ; 
			
		docs = 0 ; 
		PrintStream fout = new PrintStream ( new File ( "temp.txt" ) ) ; 		
		fout.println ( classes ) ;
		for ( i = 0 ; i < classes ; i ++ ) {
			scanner = new Scanner ( new File ( path [ i ] + "index.txt" ) ) ;
			while ( scanner.hasNextLine () ) {
				fout.println ( i + " " + path [ i ] + scanner.nextLine () ) ;
				docs ++ ; 
			}
		}
		
		fout.close () ;
		
		} catch ( Exception e ) {
			e.printStackTrace () ;
		}

	}
		
	void writeCache () {
		(new PicDegree("apple")).writeCache () ;
	}
	
	private String caleName ( String Url ) {
		int pos ; 
		String s = "" ; 
		try {
			pos = Url.lastIndexOf ( '.' ) ; 
			java.security.MessageDigest md = java.security.MessageDigest.getInstance( "MD5" );
			md.update( Url.getBytes() );
			byte [] digest = md.digest() ;
			for ( byte b : digest ) {
				s += Integer.toHexString( b & 0xff );
            }
			String localFile =  s + Url.substring ( pos, Url.length()); 
			//System.out.println ( localFile ) ;
			return localFile ; 
		} 
		catch ( Exception e ) {
			return "c:\\temp.jpg" ; 
		}
	}

	public static boolean copyFile( String a , String b ) //  Source and Destination
    {
    	boolean done= true ;
		File in = new File ( a );
		File out = new File ( b ) ;
		FileChannel inChannel = null;
		FileChannel outChannel = null;
        try {
    	
        inChannel = new
            FileInputStream(in).getChannel();
        outChannel = new
            FileOutputStream(out).getChannel();
            inChannel.transferTo(0, inChannel.size(),
                    outChannel);
        } 
        catch (IOException e) {
            //e.printStackTrace () ;
            done =  false ;
        }
        finally {           
			return done ;
        }
    }	
	
}
